home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / utilities / printer / post-1.6src.lzh / postshade.c < prev   
C/C++ Source or Header  |  1991-04-17  |  19KB  |  640 lines

  1. /* PostScript interpreter file "postshade.c" - colours and halftones */
  2. /* (C) Adrian Aylward 1989, 1991 */
  3.  
  4. # include "post.h"
  5.  
  6. /* Routines */
  7.  
  8. extern void rangecheck(int n, float *value, int min);
  9. extern void callfunc(struct object *func, float *rp1, float *rp2, int min);
  10. extern int  gcd(int n, int m);
  11.  
  12. /* Map a colour (from gray/rgb/cmyk to gray/rgb/rgbw) */
  13.  
  14. void mapcolour(int n1, float *colour1, int n2, float *colour2)
  15. {   float c, m, y, k, u, w;
  16.     if (n2 == 0) return;
  17.     if      (n1 == 1)
  18.         if      (n2 == 1)
  19.             colour2[0] = colour1[0];
  20.         else if (n2 == 3)
  21.         {   k = colour1[0];
  22.             colour2[0] = k;
  23.             colour2[1] = k;
  24.             colour2[2] = k;
  25.         }
  26.         else
  27.         {   k = colour1[0];
  28.             colour2[0] = 1.0;
  29.             colour2[1] = 1.0;
  30.             colour2[2] = 1.0;
  31.             colour2[3] = k;
  32.         }
  33.     else if (n1 == 3)
  34.         if      (n2 == 1)
  35.             colour2[0] =
  36.                 0.30 * colour1[0] + 0.59 * colour1[1] + 0.11 * colour1[2];
  37.         else if (n2 == 3)
  38.         {   colour2[0] = colour1[0];
  39.             colour2[1] = colour1[1];
  40.             colour2[2] = colour1[2];
  41.         }
  42.         else
  43.         {   c = 1.0 - colour1[0];
  44.             m = 1.0 - colour1[1];
  45.             y = 1.0 - colour1[2];
  46.             k = c;
  47.             if (m < k) k = m;
  48.             if (y < k) k = y;
  49.             callfunc(&gstate.ucr, &k, &u, -1);
  50.             callfunc(&gstate.gcr, &k, &k, 0);
  51.             c -= u;
  52.             if (c < 0.0) c = 0.0;
  53.             if (c > 1.0) c = 1.0;
  54.             m -= u;
  55.             if (m < 0.0) m = 0.0;
  56.             if (m > 1.0) m = 1.0;
  57.             y -= u;
  58.             if (y < 0.0) y = 0.0;
  59.             if (y > 1.0) y = 1.0;
  60.             colour2[0] = 1.0 - c;
  61.             colour2[1] = 1.0 - m;
  62.             colour2[2] = 1.0 - y;
  63.             colour2[3] = 1.0 - k;
  64.         }
  65.     else
  66.         if      (n2 == 1)
  67.         {   w = 1.0 - colour1[3];
  68.             u = w -
  69.                (0.30 * colour1[0] + 0.59 * colour1[1] + 0.11 * colour1[2]);
  70.             colour2[0] = (u < 0.0) ? 0.0 : u;
  71.         }
  72.         else if (n2 == 3)
  73.         {   w = 1.0 - colour1[3];
  74.             u = w - colour1[0];
  75.             colour2[0] = (u < 0.0) ? 0.0 : u;
  76.             u = w - colour1[1];
  77.             colour2[1] = (u < 0.0) ? 0.0 : u;
  78.             u = w - colour1[2];
  79.             colour2[2] = (u < 0.0) ? 0.0 : u;
  80.         }
  81.         else
  82.         {   colour2[0] = 1.0 - colour1[0];
  83.             colour2[1] = 1.0 - colour1[1];
  84.             colour2[2] = 1.0 - colour1[2];
  85.             colour2[3] = 1.0 - colour1[3];
  86.         }
  87. }
  88.  
  89. /* Set the current colour */
  90.  
  91. void setcolour(int n, float *colour)
  92. {   rangecheck(n, colour, 0);
  93.     mapcolour(n, colour, 1, &gstate.gray);
  94.     mapcolour(n, colour, 3, gstate.rgb);
  95.     mapcolour(n, colour, 4, gstate.rgbw);
  96.     gstate.shadeok = 0;
  97.     setupshade();
  98. }
  99.  
  100. /* Get the current colour in hsb format */
  101.  
  102. void gethsbcolour(float *colour)
  103. {   float h, s, b, t, cr, cg, cb;
  104.     b = gstate.rgb[0];
  105.     if (gstate.rgb[1] > b) b = gstate.rgb[1];
  106.     if (gstate.rgb[2] > b) b = gstate.rgb[2];
  107.     t = gstate.rgb[0];
  108.     if (gstate.rgb[1] < t) t = gstate.rgb[1];
  109.     if (gstate.rgb[2] < t) t = gstate.rgb[2];
  110.     t = b - t;
  111.     if (b == 0)
  112.         s = 0;
  113.     else
  114.         s = t / b;
  115.     if (s == 0)
  116.         h = 0;
  117.     else
  118.     {   cr = (b - gstate.rgb[0]) / t;
  119.         cg = (b - gstate.rgb[1]) / t;
  120.         cb = (b - gstate.rgb[2]) / t;
  121.         if      (b == gstate.rgb[0])
  122.             h =       cb - cg;
  123.         else if (b == gstate.rgb[1])
  124.             h = 2.0 + cr - cb;
  125.         else
  126.             h = 4.0 + cg - cr;
  127.     }
  128.     h = h / 6.0;
  129.     if (h < 0.0) h += 1.0;
  130.     if (h > 1.0) h -= 1.0;
  131.     colour[0] = h;
  132.     colour[1] = s;
  133.     colour[2] = b;
  134. }
  135.  
  136. /* Set the current colour in hsb format */
  137.  
  138. void sethsbcolour(float *hsb)
  139. {   float rgb[3];
  140.     float e, f, h, n, o, p, w;
  141.     rangecheck(3, hsb, 0);
  142.     h = hsb[0] * 6.0;
  143.     e = floor(h);
  144.     f = h - e;
  145.     n = 1.0 - hsb[1];
  146.     o = 1.0 - hsb[1] * f;
  147.     p = 1.0 - hsb[1] * (1.0 - f);
  148.     switch (itrunc(e))
  149.     {   default: rgb[0] = 1.0; rgb[1] = p;   rgb[2] = n;   break;
  150.         case 1:  rgb[0] = o;   rgb[1] = 1.0; rgb[2] = n;   break;
  151.         case 2:  rgb[0] = n;   rgb[1] = 1.0; rgb[2] = p;   break;
  152.         case 3:  rgb[0] = n;   rgb[1] = o;   rgb[2] = 1.0; break;
  153.         case 4:  rgb[0] = p;   rgb[1] = n;   rgb[2] = 1.0; break;
  154.         case 5:  rgb[0] = 1.0; rgb[1] = n;   rgb[2] = o;   break;
  155.     }
  156.     w = hsb[2];
  157.     rgb[0] *= w;
  158.     rgb[1] *= w;
  159.     rgb[2] *= w;
  160.     setcolour(3, rgb);
  161. }
  162.  
  163. /* Check values are in the range 0.0 to 1.0 (approximately) */
  164.  
  165. void rangecheck(int n, float *value, int min)
  166. {   float v;
  167.     while (n--)
  168.     {   v = *value;
  169.         if (min == 0)
  170.         {   if      (v <  0.0)
  171.                 if (v < -0.0001)
  172.                     error(errrangecheck);
  173.                 else
  174.                     *value =  0.0;
  175.         }
  176.         else
  177.         {   if      (v < -1.0)
  178.                 if (v < -1.0001)
  179.                     error(errrangecheck);
  180.                 else
  181.                     *value = -1.0;
  182.         }
  183.         if (v >  1.0)
  184.             if (v >  1.0001)
  185.                 error(errrangecheck);
  186.             else
  187.                 *value = 1.0;
  188.         value++;
  189.     }
  190. }
  191.  
  192. /* Call the transfer function */
  193.  
  194. void calltransfer(float *colour, float *shade)
  195. {   int plane;
  196.     for (plane = 0; plane < gstate.dev.depth; plane++)
  197.     {   if      (gstate.transdepth == 1)
  198.             callfunc(&gstate.transfer[0], colour, shade, 0);
  199.         else if (gstate.dev.depth == 1)
  200.             callfunc(&gstate.transfer[3], colour, shade, 0);
  201.         else
  202.             callfunc(&gstate.transfer[plane], colour, shade, 0);
  203.         colour++;
  204.         shade++;
  205.     }
  206. }
  207.  
  208. /* Call a (transfer, ucr, gcr) function */
  209.  
  210. void callfunc(struct object *func, float *rp1, float *rp2, int min)
  211. {   struct object token, *token1;
  212.     float r;
  213.     int nest;
  214.  
  215.     if (func->length == 0)
  216.     {   *rp2 = *rp1;
  217.         return;
  218.     }
  219.  
  220.     if (opernest == operstacksize) error(errstackoverflow);
  221.     token1 = &operstack[opernest];
  222.     token.type = typereal;
  223.     token.flags = 0;
  224.     token.length = 0;
  225.     token.value.rval = *rp1;
  226.     *token1 = token;
  227.     opernest++;
  228.     nest = opernest;
  229.     pushint();
  230.     istate.flags = intgraph;
  231.     interpret(func);
  232.     popint();
  233.     if (opernest > nest) error(errstackoverflow);
  234.     if (opernest < nest) error(errstackunderflow);
  235.     token = *token1;
  236.     if      (token1->type == typeint)
  237.         r = token1->value.ival;
  238.     else if (token1->type == typereal)
  239.         r = token1->value.rval;
  240.     else
  241.         error(errtypecheck);
  242.     rangecheck(1, &r, min);
  243.     *rp2 = r;
  244.     opernest = nest - 1;
  245. }
  246.  
  247. /* Set up the halftone shades */
  248.  
  249. void setupshade(void)
  250. {   if      (gstate.dev.depth == 1)
  251.         calltransfer(&gstate.gray, gstate.shade);
  252.     else if (gstate.dev.depth == 3)
  253.         calltransfer(gstate.rgb, gstate.shade);
  254.     else if (gstate.dev.depth == 4)
  255.         calltransfer(gstate.rgbw, gstate.shade);
  256.     gstate.shadeok = 1;
  257.     screenok = 0;
  258. }
  259.  
  260. /* Set up the halftone pattern spot arrays */
  261.  
  262. void setuphalf(void)
  263. {   struct object token, *token1;
  264.     struct halftone *htone;
  265.     char *hbeg, *hptr;
  266.     int hsize, hfree;
  267.     int size, nest;
  268.     int hpsize, hxsize, hysize;
  269.     int harea, hxrep;
  270.     int hdx, hdy;
  271.     short *spotkey;
  272.     float *spotval;
  273.     short *spotsub;
  274.     short *spotnum;
  275.     char **spotptr;
  276.     float anga, cosa, sina, xlen, ylen;
  277.     float rx, ry, cx, cy;
  278.     float spot;
  279.     int ix, iy, ia, ii;
  280.     int xxu, xyu, xxs, xys;
  281.     int yxu, yyu, yxs, yys;
  282.     int plane;
  283.  
  284.     if (istate.flags & intgraph) error(errundefined);
  285.  
  286.     /* Divide the available memory equally between the screens */
  287.  
  288.     hbeg = halfbeg;
  289.     hsize = (halfsize / gstate.screendepth) & ~(mcalign - 1);
  290.  
  291.     /* Loop through all the screens */
  292.  
  293.     htone = &halftone[0];
  294.     for (plane = 0; plane < gstate.screendepth; plane++)
  295.     {   hptr = hbeg;
  296.         hfree = hsize;
  297.  
  298.         /* Calculate the dimensions of a halftone cell.  N.B. density may be
  299.          * different in the x and y directions */
  300.  
  301.         anga = gstate.screenangle[plane] * degtorad;
  302.         cosa = cos(anga);
  303.         sina = sin(anga);
  304.         xlen = gstate.dev.xden / gstate.screenfreq[plane];
  305.         ylen = gstate.dev.yden / gstate.screenfreq[plane];
  306.         if (xlen < 1.0) xlen = 1.0;
  307.         if (ylen < 1.0) ylen = 1.0;
  308.         xxu = itrunc(fabs(xlen * cosa) + 0.5);
  309.         xyu = itrunc(fabs(xlen * sina) + 0.5);
  310.         yxu = itrunc(fabs(ylen * sina) + 0.5);
  311.         yyu = itrunc(fabs(ylen * cosa) + 0.5);
  312.         xxs = (cosa < 0.0)? -xxu:  xxu;
  313.         xys = (sina < 0.0)?  xyu: -xyu;
  314.         yxs = (sina < 0.0)? -yxu:  yxu;
  315.         yys = (cosa < 0.0)? -yyu:  yyu;
  316.  
  317.         /* The area of the cell is also the determinant of the transformation
  318.          * matrix.  The pattern repeats in the x and y directions at an
  319.          * interval equal to the area divided by the gcd of the y or x steps.
  320.          * (N.B. gcd(n,0) = n).  Round the x size up to a multiple of 8, not
  321.          * too small */
  322.  
  323.         harea = xxu * yyu + xyu * yxu;
  324.         hxrep = harea / gcd(yyu, yxu);
  325.         hysize = harea / gcd(xxu, xyu);
  326.         hxsize = hxrep / gcd(hxrep, 8);
  327.         if (hxsize < 20) hxsize *= (20 / hxsize);
  328.         hpsize = hxsize * hysize;
  329.  
  330.         /* The pattern also repeats at a distance in the y direction, equal
  331.          * to the area divided by the x repeat interval, but displaced
  332.          * sideways.  We calculate this distance so we can fill in the
  333.          * entire pattern without calling the spot function for the same
  334.          * spot twice.  To do so we follow the cell boundaries until we get
  335.          * to the y coordinate we want, keeping track of the x displacement.
  336.          * N.B. dy is calculated using the unsigned values for the cell
  337.          * length, and dx uses the signed values, so when we step dx we have
  338.          * to allow for the actual sign of the dy step */
  339.  
  340.         hdx = 0;
  341.         ii = harea / hxrep;      /* Where we want to get to */
  342.         if (ii < hysize)
  343.         {   hdy = 0;
  344.  
  345.             while (hdy != ii)    /* If y too high, step down */
  346.                 if (hdy > ii)
  347.                 {   hdy -= yyu;
  348.                     if (yys < 0)
  349.                         hdx += xys;
  350.                     else
  351.                         hdx -= xys;
  352.                 }
  353.                 else             /* Otherwise, step right */
  354.                 {   hdy += yxu;
  355.                     if (yxs < 0)
  356.                         hdx -= xxs;
  357.                     else
  358.                         hdx += xxs;
  359.                 }
  360.  
  361.             if (hdx < 0) hdx += hxrep;
  362.         }
  363.         hdy = ii * hxsize;
  364.  
  365.         /* Allocate the memory for the spot key array.  We don't allocate
  366.          * the spot value array properly, as we will have finished with it
  367.          * before we allocate anything else */
  368.  
  369.         size = harea * sizeof (short);
  370.         size = (size + (mcalign - 1)) &  ~(mcalign - 1);
  371.         if (size > hfree) error(errlimitcheck);
  372.         spotkey = (short *) hptr;
  373.         hptr += size;
  374.         hfree -= size;
  375.         size = harea * sizeof (float);
  376.         if (size > hfree) error(errlimitcheck);
  377.         spotval = (float *) hptr;
  378.  
  379.         /* Call the spot function for each point in the cell.  Step on the
  380.          * x coordinate until the pattern repeats, then step on y */
  381.  
  382.         for (ia = 0, ix = 0, iy = 0; ia < harea; ia++, ix++)
  383.         {   if (ix == hxrep)
  384.             {   ix = 0;
  385.                 iy++;
  386.             }
  387.  
  388.             /* Inverse transform the coordinates from the pattern back to
  389.              * the cell space */
  390.  
  391.             rx = ix + 0.5;
  392.             ry = iy + 0.5;
  393.             cx = (rx * yys - ry * xys) / harea;
  394.             cy = (ry * xxs - rx * yxs) / harea;
  395.             cx = cx - floor(cx);
  396.             cy = cy - floor(cy);
  397.             cx = cx + cx - 1.0;
  398.             cy = cy + cy - 1.0;
  399.  
  400.             /* Call the spot function */
  401.  
  402.             if (opernest + 2 > operstacksize) error(errstackoverflow);
  403.             token1 = &operstack[opernest];
  404.             token.type = typereal;
  405.             token.flags = 0;
  406.             token.length = 0;
  407.             token.value.rval = cx;
  408.             token1[0] = token;
  409.             token.value.rval = cy;
  410.             token1[1] = token;
  411.             opernest += 2;
  412.             nest = opernest - 1;
  413.             pushint();
  414.             istate.flags = intgraph;
  415.             interpret(&gstate.screenfunc[plane]);
  416.             popint();
  417.             if (opernest > nest) error(errstackoverflow);
  418.             if (opernest < nest) error(errstackunderflow);
  419.             token = *token1;
  420.             if      (token1->type == typeint)
  421.                 spot = token1->value.ival;
  422.             else if (token1->type == typereal)
  423.                 spot = token1->value.rval;
  424.             else
  425.                 error(errtypecheck);
  426.             rangecheck(1, &spot, -1);
  427.             opernest = nest - 1;
  428.  
  429.             /* Save the value in the spot array */
  430.  
  431.             spotval[ia] = spot;
  432.             spotkey[ia] = ia;
  433.         }
  434.  
  435.         /* Shell sort the spot array */
  436.  
  437.         ia = harea;
  438.         for (;;)
  439.         {   ia = ia / 3 + 1;
  440.             for (ix = ia; ix < harea; ix++)
  441.                 for (iy = ix - ia;
  442.                      iy >= 0 &&
  443.                          spotval[spotkey[iy]] > spotval[spotkey[iy + ia]];
  444.                      iy -= ia)
  445.                 {   ii = spotkey[iy];
  446.                     spotkey[iy] = spotkey[iy + ia];
  447.                     spotkey[iy + ia] = ii;
  448.                 }
  449.             if (ia == 1) break;
  450.         }
  451.  
  452.         /* Initialise the pattern cache.  Make sure we have room for at
  453.          * least one slot (or at least the number of planes) */
  454.  
  455.         size = (harea + 1) * sizeof (char *);
  456.         if (size > hfree) error(errlimitcheck);
  457.         spotptr = (char **) hptr;
  458.         hptr += size;
  459.         hfree -= size;
  460.         size = (harea + 1) * sizeof (short);
  461.         if (size * 2 > hfree) error(errlimitcheck);
  462.         spotsub = (short *) hptr;
  463.         hptr += size;
  464.         spotnum = (short *) hptr;
  465.         hptr += size;
  466.         hfree -= size * 2;
  467.         if (hpsize *
  468.                 ((gstate.screendepth == 1) ? gstate.dev.depth : 1) > hfree)
  469.             error(errlimitcheck);
  470.  
  471.         for (ia = 0; ia <= harea; ia++)
  472.             spotsub[ia] = -1;
  473.  
  474.         for (ia = 0; ia <= harea ; ia++)
  475.         {   spotnum[ia] = -1;
  476.             spotptr[ia] = hptr;
  477.             hptr += hpsize;
  478.             hfree -= hpsize;
  479.             if (hfree < hpsize) break;
  480.         }
  481.  
  482.         /* Store the results in the halftone structure */
  483.  
  484.         htone->psize = hpsize;
  485.         htone->xsize = hxsize;
  486.         htone->ysize = hysize;
  487.         htone->area = harea;
  488.         htone->xrep = hxrep;
  489.         htone->dx = hdx;
  490.         htone->dy = hdy;
  491.         htone->spotkey = spotkey;
  492.         htone->spotsub = spotsub;
  493.         htone->spotnum = spotnum;
  494.         htone->spotptr = spotptr;
  495.         htone->spotmax = ia;
  496.         htone->spotnext = -1;
  497.         htone++;
  498.         hbeg += hsize;
  499.     }
  500.  
  501.     halfok = gnest;
  502.     screenok = 0;
  503. }
  504.  
  505. /* Set up the halftone screens */
  506.  
  507. void setupscreen(float *shade)
  508. {   struct halfscreen *hscreen;
  509.     struct halftone *htone;
  510.     char *hptr;
  511.     int hnum;
  512.     int hpsize, hxsize;
  513.     int harea, hxrep, hxbits;
  514.     int hdx, hdy;
  515.     int ix, iy, ia, ii;
  516.     int plane;
  517.  
  518.     screenok = 0;
  519.     hscreen = &halfscreen[0];
  520.  
  521.     for (plane = 0; plane < gstate.dev.depth; plane++, hscreen++)
  522.     {   if (gstate.screendepth == 1)
  523.             htone = &halftone[0];
  524.         else if (gstate.dev.depth == 1)
  525.             htone = &halftone[3];
  526.         else
  527.             htone = &halftone[plane];
  528.  
  529.         /* We never use a halftone for black or white */
  530.  
  531.         hscreen->halftone = htone;
  532.         hscreen->num = hnum = itrunc(htone->area * (*shade++ + 0.0001));
  533.         if (hnum == 0 || hnum == htone->area) continue;
  534.  
  535.         /* Look in the cache */
  536.  
  537.         ii = htone->spotsub[hnum];
  538.         if (ii != -1)
  539.         {   hscreen->ptr = htone->spotptr[ii];
  540.             continue;
  541.         }
  542.  
  543.         /* Use the next cache slot (cyclic replacement). */
  544.  
  545.         htone->spotnext++;
  546.         if (htone->spotnext > htone->spotmax) htone->spotnext = 0;
  547.         ii = htone->spotnum[htone->spotnext];
  548.         if (ii != -1) htone->spotsub[ii] = -1;
  549.         htone->spotsub[hnum] = htone->spotnext;
  550.         htone->spotnum[htone->spotnext] = hnum;
  551.         hscreen->ptr = hptr = htone->spotptr[htone->spotnext];
  552.  
  553.         /* Load the variables from the halftone structure */
  554.  
  555.         hpsize = htone->psize;
  556.         hxsize = htone->xsize;
  557.         hxbits = hxsize * 8;
  558.         harea = htone->area;
  559.         hxrep = htone->xrep;
  560.         hdx = htone->dx;
  561.         hdy = htone->dy;
  562.  
  563.         /* Initialise the pattern.  The highest screen is all white. */
  564.  
  565.         if (hnum == harea)
  566.             memset(hptr, 0x00, hpsize);
  567.  
  568.         /* We base our pattern on the next lowest one that is in the
  569.          * cache,  or a black screen if we can't find any other */
  570.  
  571.         else
  572.         {   ia = hnum;
  573.             for (;;)
  574.             {   if (ia == 0)
  575.                 {   memset(hptr, 0xff, hpsize);
  576.                     break;
  577.                 }
  578.                 ia--;
  579.                 ii = htone->spotsub[ia];
  580.                 if (ii >= 0)
  581.                 {   memcpy(hptr, htone->spotptr[ii], hpsize);
  582.                     break;
  583.                 }
  584.             }
  585.  
  586.             /* Loop for each spot value greater than the screen number */
  587.  
  588.             for (; ia < hnum; ia++)
  589.             {
  590.                 /* Clear the corresponding bit in each cell */
  591.  
  592.                 ii = htone->spotkey[ia];
  593.  
  594.                 /* Loop through all the rows containing the bit */
  595.  
  596.                 iy = (ii / hxrep) * hxsize;
  597.                 ii = ii % hxrep;
  598.                 while (iy < hpsize)
  599.                 {
  600.                     /* Loop replicating the bit it up to the x size */
  601.  
  602.                     for (ix = ii; ix < hxbits; ix += hxrep)
  603.                         hptr[iy + (ix >> 3)] &= (~0x0080) >> (ix & 7);
  604.  
  605.                     /* Step on to the next row */
  606.  
  607.                     ii += hdx;
  608.                     if (ii >= hxrep) ii -= hxrep;
  609.                     iy += hdy;
  610.                 }
  611.             }
  612.         }
  613.     }
  614. }
  615.  
  616. /* Find the greatest common divisor of two positive integers.  If one is
  617.  * zero the result is the other */
  618.  
  619. int gcd(int n, int m)
  620. {   unsigned int n1, m1, r;
  621.     if      (n > m)
  622.     {   n1 = n;
  623.         m1 = m;
  624.     }
  625.     else if (m > n)
  626.     {   n1 = m;
  627.         m1 = n;
  628.     }
  629.     else
  630.         return n;
  631.     while (m1 != 0)
  632.     {   r = n1 % m1;
  633.         n1 = m1;
  634.         m1 = r;
  635.     }
  636.     return (int) n1;
  637. }
  638.  
  639. /* End of file "postshade.c" */
  640.